package com.gtmc.gclub.chat.controller;

import java.beans.IntrospectionException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.gtmc.gclub.chat.bean.MyException;
import com.gtmc.gclub.chat.bean.Result;
import com.gtmc.gclub.chat.conimp.WxControllerImpl;
import com.gtmc.gclub.chat.constants.ChatConstant;
import com.gtmc.gclub.chat.constants.ChatErrorCode;
import com.gtmc.gclub.chat.constants.CommonProperties;
import com.gtmc.gclub.chat.dao.TmCarOwnerMapper;
import com.gtmc.gclub.chat.dao.TmPotentialUserMapper;
import com.gtmc.gclub.chat.dao.TrUserEnterpriseMapper;
import com.gtmc.gclub.chat.dao.WxChatLogMapper;
import com.gtmc.gclub.chat.dao.WxUserOwnerMapper;
import com.gtmc.gclub.chat.dto.ChatMsgDetailDto;
import com.gtmc.gclub.chat.dto.WxChatLogExportDto;
import com.gtmc.gclub.chat.dto.WxChatUserChangDto;
import com.gtmc.gclub.chat.dto.WxGzMessageDto;
import com.gtmc.gclub.chat.external.service.WeChatPushServiceInterface;
import com.gtmc.gclub.chat.jmessage.UserOperator;
import com.gtmc.gclub.chat.model.TmCarOwner;
import com.gtmc.gclub.chat.model.TmChatDialogue;
import com.gtmc.gclub.chat.model.TmPotentialUser;
import com.gtmc.gclub.chat.model.TmUsers;
import com.gtmc.gclub.chat.model.TrUserEnterprise;
import com.gtmc.gclub.chat.model.WxChatLog;
import com.gtmc.gclub.chat.model.WxChatLoginLog;
import com.gtmc.gclub.chat.model.WxMaterialFile;
import com.gtmc.gclub.chat.model.WxToken;
import com.gtmc.gclub.chat.model.WxUserOwner;
import com.gtmc.gclub.chat.modelutil.WxMaterialModelToH5;
import com.gtmc.gclub.chat.service.AppApiService;
import com.gtmc.gclub.chat.service.ChatWaitQueueService;
import com.gtmc.gclub.chat.service.FileService;
import com.gtmc.gclub.chat.service.OwnerService;
import com.gtmc.gclub.chat.service.WxChatLoginLogService;
import com.gtmc.gclub.chat.service.WxChatUserService;
import com.gtmc.gclub.chat.service.WxMaterialFileService;
import com.gtmc.gclub.chat.service.WxService;
import com.gtmc.gclub.chat.service.WxUserService;
import com.gtmc.gclub.chat.util.BeanMapUtil;
import com.gtmc.gclub.chat.util.DateUtil;
import com.gtmc.gclub.chat.util.JmessageUserUtil;
import com.gtmc.gclub.chat.util.MessageOperate;
import com.gtmc.gclub.chat.util.Pair;
import com.gtmc.gclub.chat.util.RandomNum;
import com.gtmc.gclub.chat.util.SimpleExcelExport;
import com.gtmc.gclub.chat.vo.ChangeChatVo;
import com.gtmc.gclub.chat.vo.ChatCommonContent;
import com.gtmc.gclub.chat.vo.ClassifyContentPageVo;
import com.gtmc.gclub.chat.vo.H5MessageVo;
import com.gtmc.gclub.chat.vo.TmCarOwnerVo;
import com.gtmc.gclub.chat.vo.TrUserEnterpriseVo;
import com.gtmc.gclub.chat.vo.WxChatLogExportVo;
import com.gtmc.gclub.chat.vo.WxMaterialBaseVo;
import com.gtmc.gclub.chat.vo.WxMaterialDetailH5;
import com.gtmc.gclub.chat.vo.WxMaterialFileVo;
import com.gtmc.gclub.chat.vo.WxMaterialMedia;
import com.gtmc.gclub.chat.vo.WxMaterialNews;
import com.gtmc.gclub.common.WxMaterialTypeEnum;
import com.gtmc.gclub.common.WxMediaFileSourceType;
import com.gtmc.gclub.common.WxUtil;
import com.gtmc.gclub.wx.dto.JmessAuth;
import com.gtmc.gclub.wx.dto.QyUserInfo;
import com.gtmc.gclub.wx.dto.WxJsApiAuth;
import com.infoservice.filestore.FileStore;

import io.swagger.annotations.ApiOperation;

@Controller
@RequestMapping(value = "/chat/wx")
public class WxController extends BaseController {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private ChatController chatController;

	@Autowired
	private AppApiService appApiService;

	@Autowired
	private WxService wxService;

	@Autowired
	private WxUserService wxUserService;
	
	@Autowired
	private WxChatUserService wxChatUserService;
	@Autowired
	private WxMaterialFileService wxMaterialFileService;

	@Autowired
	private CommonProperties commonProperties;
	
	@Autowired
	private TmCarOwnerMapper tmCarOwnerMapper;
	
	@Autowired
	private TmPotentialUserMapper tmPotentialUserMapper;
	
	@Autowired
	private WxChatLogMapper wxChatLogMapper;
	
	@Autowired
	private TrUserEnterpriseMapper trUserEnterpriseMapper;
	
	@Autowired
	private OwnerService ownerService;
	
	@Autowired
	private UserOperator userOperator;
	
	@Autowired
	private FileService fileService;
	
	@Autowired
	private WeChatPushServiceInterface weChatPushServiceInterface;
	
	@Autowired
	private WxControllerImpl controllerImpl;
	
	@Autowired
	private WxChatLoginLogService wxChatLoginLogService;
	
	private ChatWaitQueueService chatQueueService = ChatWaitQueueService.newInstance();

	/**
	 * 聊天登陆
	 * 
	 * @param userId
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/wx_chat_login", method = RequestMethod.GET)
	@ApiOperation(value = "登陆接口", notes = "登陆接口")	
	public String wxLogin(@RequestParam(value = "code", required = true) String code,
			@RequestParam(value = "state", required = true) String state, Model model) {
		logger.info("微信登录接口");
		// 获取token
		WxToken token = wxService.getWxToken();
		// 获取微信用户信息
		QyUserInfo userInfo = WxUtil.getUserInfo(token.getAccessToken(), code);
		if (userInfo.getUserId() == null || "".equals(userInfo.getUserId())) {
			// 微信异常，或者用户无访问权限
			throw new MyException("back");

		}
		// 查询用户是否存在
		TrUserEnterprise user = wxUserService.getFirstWxChatUser(token.getAccessToken(), userInfo.getUserId());
		model.addAttribute("userInfo", user);
		model.addAttribute("checkFirst", RandomNum.createRandomString(6));
		// 存在用户，则判断WX企业号的H5对应的Jmessage是否已经注册，若无，则注册
//		if(StringUtils.isEmpty(user.getWxJmessageCode())) {
//			// 没有则注册
//			String wxJmessage = JmessageUserUtil.getJmessageWXCode(user.getDealerCode(), user.getUserId());
//			// 注册客服自己的jmessage账号，和聊天向对应的账号
//			Result<Map> regResult = userOperator.registerAdmins(wxJmessage, ChatConstant.JMESSAGE_DEFAULT_PWD);
//			if (regResult.getReturnFlag() != 1) {// 注册失败
//				logger.error("Jmessage账号注册失败："+wxJmessage);
//			}else {
//				// 修改数据库
//				user.setWxJmessageCode(wxJmessage);
//				if (wxChatUserService.updateChatInfo(user) <= 0) {
//					logger.error("Jmessage账号注册成功，写入数据库失败："+user);
//				}else {
//					logger.debug("Jmessage账号注册成功 "+wxJmessage);
//				}
//			}
//		}
		return "chat/wxchat/chat_list";
	}

	@RequestMapping(value = "/wx_chat_customer", method = RequestMethod.GET)
	@ResponseBody
	public Result<List<Map<String, Object>>> getCustomer(
			@RequestBody Integer userId) {
		// @RequestParam(value = "pageCurrent", required = true) Integer
		// pageCurrent,
		// @RequestParam(value = "pageSize", required = true) Integer
		// pageSize,
		// 获取客户列表
		return new Result<List<Map<String, Object>>>(1, wxUserService.getWxChatList(wxChatUserService.getChatUserIdByLKUserId(userId),null), null);
	}

	/**
	 * 调试使用
	 * 
	 * @param userId
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/wx_chat_reload", method = RequestMethod.GET)
	public String wxChat(@RequestParam(value = "wxCode", required = true) String wxCode, Model model) {
		logger.info("刷新chatList页面");
		TrUserEnterprise user = wxUserService.getFirstWxChatUser1(null, wxCode);
		model.addAttribute("userInfo", user);
		return "chat/wxchat/chat_list";
	}

	/**
	 * 跳转聊天页面
	 * 
	 * @param ownerCode
	 * @param userId
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/wx_chat", method = RequestMethod.GET)
	@ApiOperation(value = "跳转聊天界面", notes = "跳转聊天界面")	
	public String wxChat(@RequestParam(value = "ownerCode", required = true) String ownerCode,
			@RequestParam(value = "userId", required = true) String userId,
			@RequestParam(value = "dealerCode", required = true) String dealerCode,
			@RequestParam(value = "wxCode", required = true) String wxCode, Model model) {
		logger.info("进入chat页面:wxChat");
		model.addAttribute("userId", userId);
		model.addAttribute("wxCode", wxCode);
		model.addAttribute("ownerCode", ownerCode);
		model.addAttribute("dealerCode", dealerCode);
		return "chat/wxchat/chat";
	}

	/**
	 * 查询聊天 用户-客户信息
	 * 
	 * @param ownerCode
	 * @param userId
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/wx_chat_userInfo", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "查询聊天 用户-客户信息", notes = "{\"ownerCode\":\"\",\"userId\":\"\",\"url\":\"\"}")	
	public Result<Map<String, Object>> wxChatUserInfo(
			@RequestBody Map<String,Object> params
//			@RequestParam(value = "ownerCode", required = true) String ownerCode,
//			@RequestParam(value = "userId", required = true) String userId,
//			@RequestParam(value = "url", required = true) String url
			) {
		String ownerCode = (String)params.get("ownerCode");
		String userIdLk = (String)params.get("userId");
		String userId = wxChatUserService.getChatUserIdByLKUserId(Integer.valueOf(userIdLk)).toString();
		String url = (String)params.get("url");
		logger.info("获取聊天用户信息:wxChatUserInfo");
		Map<String, Object> map = wxUserService.getUserInfo(ownerCode, userId);
		try {
			JmessAuth auth = wxUserService.getJmessAuth();
			WxJsApiAuth jsAuth = wxService.getWxJsApiAuth(url);
			map.put("auth", auth);
			map.put("jsAuth", jsAuth);
		} catch (Exception e) {
			logger.error("查询auth出错", e);
		}
		return new Result<Map<String, Object>>(1, map, null);
	}

	@RequestMapping(value = "/wx_js_sdk", method = RequestMethod.GET)
	@ResponseBody
	public Result<WxJsApiAuth> getJsSdk(@RequestParam(value = "url", required = true) String url) {
		return new Result<WxJsApiAuth>(1, wxService.getWxJsApiAuth(url), null);
	}

	/**
	 * 查询聊天对话信息 - 聊天记录
	 * 
	 * @param ownerCode
	 * @param userId
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/wx_chat_talk", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "查询聊天对话信息", 
	notes = "{\"pageCurrent\":1,\"pageSize\":1,\"ownerCode\":\"1212589\",\"userId\":39981,\"lastTime\":00000000000000}")	
	public Result<List<Map<String, Object>>> wxChatTalk(
			@RequestBody Map<String,Object> params
//			@RequestParam(value = "pageCurrent", required = true) Integer pageCurrent,
//			@RequestParam(value = "pageSize", required = true) Integer pageSize,
//			@RequestParam(value = "ownerCode", required = true) String ownerCode,
//			@RequestParam(value = "userId", required = true) String userId,
//			@RequestParam(value = "chatId", required = false) Integer chatId,
//			@RequestParam(value = "lastTime", required = false) Long lastTime
			) {
		Integer pageCurrent = Integer.valueOf(params.get("pageCurrent").toString());
		Integer pageSize = Integer.valueOf(params.get("pageSize").toString());
		String ownerCode = (String)params.get("ownerCode");
		Integer userIdLk = Integer.valueOf(params.get("userId").toString());
		String userId = wxChatUserService.getChatUserIdByLKUserId(userIdLk).toString();
		Integer chatId = params.get("chatId")==null ? null : Integer.valueOf(params.get("chatId").toString());
		Long lastTime = params.get("lastTime")==null ? null : (Long.parseLong(params.get("lastTime").toString())) ;
		logger.info("获取聊天详情:wxChatTalk");
		// 根据产品要求：展示聊天列表的时候，以客户为主，展示和客户相关的所有的聊天记录，当前客服给direction 0非当前客服给direction 2
		List<Map<String, Object>> list = wxUserService.getWxChatTalk(null, ownerCode, pageCurrent, pageSize, chatId,
				lastTime);
		// 对direction进行加工:direction 0 客服 1 客户 2 其他客服
		for(Map<String, Object> entity : list) {
			if(entity.get("direction")!=null && "0".equals(entity.get("direction").toString())) {
				if(entity.get("wxUserId")!=null && !userId.equals(entity.get("wxUserId").toString())) {
					entity.put("direction", "2");
				}
			}
		}
		return new Result<List<Map<String, Object>>>(1, list, null);
	}

	/**
	 * 发送信息接口
	 * 
	 * @param ownerCode
	 * @param userId
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping(value = "/wx_sendMessage", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "发送消息接口", notes = "原参数：ownerCode=toUserName,userId=fromUserName，其他不变<br/>FromUserName本人ID,ToUserName用户Code.详细参见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547")	
	public Result<String> sendMessage(@RequestBody WxGzMessageDto wxmsgDto
			) throws Exception {
		String ownerCode = wxmsgDto.getToUserName();
		Integer userIdLk = Integer.valueOf(wxmsgDto.getFromUserName());// 确保fromUser是管理后台的ID，非客服的主键ID
		String userId = wxChatUserService.getChatUserIdByLKUserId(userIdLk).toString();
		String content = wxmsgDto.getContent();
		// 这个接口是发送普通消息接口，消息类型为text
		if(StringUtils.isEmpty(wxmsgDto.getMsgType())) {
			wxmsgDto.setMsgType(WxMaterialTypeEnum.text.name());
		}
		logger.info("发送信息接口:sendMessage，类型为text - "+wxmsgDto.getMsgType());
		logger.info("参数列表："+ownerCode + "," + userId + "," + content);
		TrUserEnterprise chatuser = wxUserService.getWxChatUser(userId);
		WxUserOwner userForChat = wxUserService.getWxUserOwner(userId, ownerCode);
		// 为了保证业务的正常进行，客服不允许向未练级的用户发送消息
		if(userForChat==null || userForChat.getStatus()==0) {
			return new Result<String>(0,null,"和此用户的聊天链接已断开");
		}
		TmPotentialUser userQuery = new TmPotentialUser();
		userQuery.setPotentialUserId(new BigDecimal(ownerCode));
		TmPotentialUser user = ownerService.getOne(userQuery);
		logger.debug("更新登录日志:"+wxmsgDto.getJmessageCode()+"=="+chatuser.getJmessageCode()+" ? "+StringUtils.equals(wxmsgDto.getJmessageCode(), chatuser.getJmessageCode()));
		wxChatLoginLogService.updateTime(Integer.valueOf(userIdLk), (StringUtils.equals(wxmsgDto.getJmessageCode(), chatuser.getJmessageCode()) ? WxChatLoginLog.APP_PC : WxChatLoginLog.APP_QY));
		Result<String> sendMessageToWxPublish = null ;
		if(WxMaterialTypeEnum.text.name().equals(wxmsgDto.getMsgType())) {
			sendMessageToWxPublish = wxUserService.sendMessageToWxPublish(wxmsgDto, chatuser, userForChat, user);
		}else {
			String contentFileUrl = null ;
			String contentTitle = null ;
			String contentDescription = null ;
			if(WxMaterialTypeEnum.mpnews.name().equals(wxmsgDto.getMsgType()) || WxMaterialTypeEnum.news.name().equals(wxmsgDto.getMsgType())) {
				contentFileUrl = wxmsgDto.getUrl();
				contentTitle = wxmsgDto.getTitle();
				contentDescription = wxmsgDto.getDescription();
			}else {
				// 这里为了能让H5和聊天记录访问到，从微信中获取媒体文件，然后将URL做为content存储到聊天记录中
				// 这里操作的是永久素材，请到永久素材中去获取
				WxMaterialFileVo fileUrlEntity = wxService.getFileUrl(wxmsgDto.getMediaId(),WxMaterialTypeEnum.valueOf(wxmsgDto.getMsgType()),WxMediaFileSourceType.permanent);
				contentFileUrl = fileUrlEntity.getLocalUrl();
				contentTitle = StringUtils.isEmpty(wxmsgDto.getTitle()) ? fileUrlEntity.getTitle() : wxmsgDto.getTitle();
				contentDescription = fileUrlEntity.getDescription();
				logger.debug("媒体文件已经上传到本地，URL:"+contentFileUrl);
			}
			logger.debug("前端给的title:"+wxmsgDto.getTitle()+";最终设置的title:"+contentTitle);
			wxmsgDto.setContent(contentFileUrl);
			wxmsgDto.setTitle(contentTitle);
			sendMessageToWxPublish = wxUserService.sendMediaMessageToWxPublish(chatuser, userForChat, user, 0,wxmsgDto);
		}
		return sendMessageToWxPublish;
	}
	/**
	 * 发送媒体信息接口
	 * 
	 * @param ownerCode
	 * @param userId
	 * @return
	 * @throws Exception 
	 */
//	@RequestMapping(value = "/wx_sendMediaMessage", method = RequestMethod.POST)
//	@ResponseBody
//	@ApiOperation(value = "发送媒体消息接口", notes = "FromUserName本人ID,ToUserName用户Code.详细参见：https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547")	
//	public Result<String> sendMediaMessage(@RequestBody WxGzMessageDto wxmsgDto) throws Exception {
//		logger.info("发送媒体信息接口:sendMediaMessage");
//		logger.info("参数列表："+wxmsgDto);
//		String ownerCode = wxmsgDto.getToUserName();
//		String userIdLks = wxmsgDto.getFromUserName();
//		Integer userIdLk = userIdLks == null ? null : Integer.parseInt(userIdLks);
//		String userId = wxChatUserService.getChatUserIdByLKUserId(userIdLk).toString();
//		WxMaterialTypeEnum type = WxMaterialTypeEnum.valueOf(wxmsgDto.getMsgType());
//		logger.debug("发送媒体消息：ownerCode："+ownerCode+";userIdLks："+userIdLks+";type："+type+";");
//		String contentFileUrl = null ;
//		String contentTitle = null ;
//		String contentDescription = null ;
//		if(WxMaterialTypeEnum.mpnews.name().equals(wxmsgDto.getMsgType()) || WxMaterialTypeEnum.news.name().equals(wxmsgDto.getMsgType())) {
//			contentFileUrl = wxmsgDto.getUrl();
//			contentTitle = wxmsgDto.getTitle();
//			contentDescription = wxmsgDto.getDescription();
//		}else {
//			// 这里为了能让H5和聊天记录访问到，从微信中获取媒体文件，然后将URL做为content存储到聊天记录中
//			// 这里操作的是永久素材，请到永久素材中去获取
//			WxMaterialFileVo fileUrlEntity = wxService.getFileUrl(wxmsgDto.getMediaId(),WxMaterialTypeEnum.valueOf(wxmsgDto.getMsgType()),WxMediaFileSourceType.permanent);
//			contentFileUrl = fileUrlEntity.getLocalUrl();
//			contentTitle = StringUtils.isEmpty(wxmsgDto.getTitle()) ? fileUrlEntity.getTitle() : wxmsgDto.getTitle();
//			contentDescription = fileUrlEntity.getDescription();
//			logger.debug("媒体文件已经上传到本地，URL:"+contentFileUrl);
//		}
//		logger.debug("前端给的title:"+wxmsgDto.getTitle()+";最终设置的title:"+contentTitle);
//		wxmsgDto.setContent(contentFileUrl);
//		TrUserEnterprise chatuser = wxUserService.getWxChatUser(userId);
//		WxUserOwner userForChat = wxUserService.getWxUserOwner(userId, ownerCode);
//		TmPotentialUser userQuery = new TmPotentialUser();
//		userQuery.setPotentialUserId(new BigDecimal(ownerCode));
//		TmPotentialUser user = ownerService.getOne(userQuery);
//		wxmsgDto.setTitle(contentTitle);
//		logger.debug("更新登录日志:"+wxmsgDto.getJmessageCode()+"=="+chatuser.getJmessageCode()+" ? "+StringUtils.equals(wxmsgDto.getJmessageCode(), chatuser.getJmessageCode()));
//		wxChatLoginLogService.updateTime(Integer.valueOf(userIdLk), (StringUtils.equals(wxmsgDto.getJmessageCode(), chatuser.getJmessageCode()) ? WxChatLoginLog.APP_PC : WxChatLoginLog.APP_QY));
//		return wxUserService.sendMediaMessageToWxPublish(chatuser, userForChat, user, 0,wxmsgDto);
//	}

	@RequestMapping(value = "/wx_sendimage", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "发送图片消息接口", notes = "{\"ownerCode\":\"\",\"userId\":\"\",\"file\":\"File\"}")	
	public Result<String> sendImage(
			@RequestParam(value = "ownerCode", required = true) String ownerCode,
			@RequestParam(value = "userId", required = true) Integer userIdLk,
			@RequestParam(value = "dateShow", required = false) Integer dateShow,
			@RequestParam(value = "file", required = true) MultipartFile file,
			@RequestParam(value = "jmessageCode", required = true) String jmessageCode
			) throws IOException {
		String userId = wxChatUserService.getChatUserIdByLKUserId(userIdLk).toString();
		TrUserEnterprise chatuser = wxUserService.getWxChatUser(userId);
		WxUserOwner userForChat = wxUserService.getWxUserOwner(userId, ownerCode);
		// 为了保证业务的正常进行，客服不允许向未练级的用户发送消息
		if(userForChat==null || userForChat.getStatus()==0) {
			return new Result<String>(0,null,"和此用户的聊天链接已断开");
		}
		TmPotentialUser chatQuery = new TmPotentialUser();
		chatQuery.setPotentialUserId(new BigDecimal(ownerCode));
		TmPotentialUser user = ownerService.getOne(chatQuery);
		// 上传到fireStore，存储文件，方便展示
		String contentFileUrl = fileService.uploadFile(file, WxMaterialTypeEnum.image.name());
		// 上传到本地目录，方便上传到微信
		String fileUrl = fileService.uploadFileForLocal(file,WxMaterialTypeEnum.image);
		File imageFile = new File(fileUrl);
		logger.debug("发送的图片大小："+imageFile.length());
		String mediaId = wxService.uploadFileToWeixin(imageFile, WxMaterialTypeEnum.image);
//		return wxUserService.sendMessageToWxPublish(mediaId, user, userForChat, chat, 0,WxMaterialTypeEnum.image);
		WxGzMessageDto wxgzMsg = new WxGzMessageDto();
		wxgzMsg.setFromUserName(chatuser.getId().toString());
		wxgzMsg.setToUserName(user.getDeviceOpenId());
		wxgzMsg.setMsgType(WxMaterialTypeEnum.image.name());
		wxgzMsg.setContent(contentFileUrl);
		wxgzMsg.setUrl(fileUrl);
		wxgzMsg.setMediaId(mediaId);
		wxgzMsg.setJmessageCode(jmessageCode);
		logger.debug("更新登录日志:"+jmessageCode+"=="+chatuser.getJmessageCode()+" ? "+StringUtils.equals(jmessageCode, chatuser.getJmessageCode()));
		wxChatLoginLogService.updateTime(Integer.valueOf(userIdLk), (StringUtils.equals(jmessageCode, chatuser.getJmessageCode()) ? WxChatLoginLog.APP_PC : WxChatLoginLog.APP_QY));
		return wxUserService.sendMediaMessageToWxPublish(chatuser, userForChat, user, 0,wxgzMsg);
	}

	/**
	 * 
	 * @author qianjs163@163.com 2017年2月9日 下午2:59:14
	 * @return
	 */
	@RequestMapping(value = "/wx_im_sdk", method = RequestMethod.GET)
	@ResponseBody
	public Result<JmessAuth> getImSdk() {
		return new Result<JmessAuth>(1, wxUserService.getJmessAuth(), null);
	}

	@RequestMapping(value = "/wx_updateTime", method = RequestMethod.GET)
	@ResponseBody
	public Result<Integer> updateTime(@RequestParam(value = "id", required = true) String id) {
		logger.info("更新时间:updateTime");
		logger.info("id" + id);
		return new Result<Integer>(1, wxUserService.updateUserOwner(Integer.valueOf(id)), null);
	}
	
	@RequestMapping(value = "/getWxChatContent", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "WX-->获取常用内容", notes = "String", produces = "application/json; charset=utf-8") // 
	public Result<List<ChatCommonContent>> getWxChatContent(
			@RequestParam(value = "dealerCode", required = false) String dealerCode
			) throws Exception {
		logger.info("getWxChatContent==>");
		List<ChatCommonContent> page = appApiService.getWxChatContent2(dealerCode);
		return new Result<List<ChatCommonContent>>(1, page, null);
	}
	// 此接口待图文整合到上面接口之后，删除
	@RequestMapping(value = "/getWxChatMediaContent", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "WX-->获取常用媒体内容", notes = "{\"dealerCode\":\"BUKA001\",\"type\":\"video\"}", produces = "application/json; charset=utf-8") 
	public Result<List<Map<String, Object>>> getWxChatMediaContent(
			@RequestParam(value = "dealerCode", required = true) String dealerCode,
			@RequestParam(value = "type", required = true) String type
			) throws Exception {
		logger.info("获取图文、视频常见内容：getWxChatMediaContent==>");
		List<Map<String,Object>> res = new ArrayList<Map<String,Object>>();
		if(!(StringUtils.equals(type, WxMaterialTypeEnum.news.name()) || StringUtils.equals(type, WxMaterialTypeEnum.mpnews.name()))) {
//			List<WxMaterialBaseVo> allMaterial = wxService.getAllMaterial(WxMaterialTypeEnum.valueOf(type));
			WxMaterialFile query = new WxMaterialFile();
			query.setAppid(WxMaterialFile.APPID_GZ);
			query.setStatus(WxMaterialFile.STATUS_USEFUL);
			query.setType(WxMaterialTypeEnum.valueOf(type));
			List<WxMaterialFile> allMaterial = wxMaterialFileService.getAll(query);
			for(WxMaterialFile tempEntity : allMaterial) {
				WxMaterialDetailH5 h5Entity = WxMaterialModelToH5.modelToH5(tempEntity);
				if(!StringUtils.equals(type, WxMaterialTypeEnum.text.name()) && !StringUtils.equals(type, WxMaterialTypeEnum.news.name()) 
						&& !StringUtils.equals(type, WxMaterialTypeEnum.mpnews.name())) {
//					WxMaterialMedia tempMedia = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(tempObj)), WxMaterialMedia.class);
//					logger.debug("获取的"+type+"素材信息："+JSON.toJSONString(tempObj));
//					res.add(WxMaterialMedia.getH5JsonMap(tempMedia,WxMaterialTypeEnum.valueOf(type)));
//					res.add(h5Entity.getWxMaterialMediaForH5());
					res.add(WxMaterialModelToH5.getWxMaterialMediaForH5(tempEntity));
				}else if (StringUtils.equals(type, WxMaterialTypeEnum.news.name()) || StringUtils.equals(type, WxMaterialTypeEnum.mpnews.name())) {
//					WxMaterialNews tempMedia = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(tempObj)), WxMaterialNews.class);
//					logger.debug("获取的"+type+"素材信息："+JSON.toJSONString(tempObj));
//					res.add(WxMaterialNews.getH5JsonMap(tempMedia));
//					res.add(h5Entity.getWxMaterialNewsForH5());
					res.add(WxMaterialModelToH5.getWxMaterialNewsForH5(tempEntity));
				}
			}
			logger.debug("参数整合结束："+res.size());
		}else {
			logger.info("获取图文、视频常见内容：getWxChatMediaContent==>");
			List<WxMaterialBaseVo> allMaterial = wxService.getAllMaterial(WxMaterialTypeEnum.valueOf(type));
			System.out.println("直接从微信端获取的"+type+"素材列表："+allMaterial.size());
			for(WxMaterialBaseVo tempRoot : allMaterial) {
				List<Object> tempMedias = tempRoot.getItem();
				for(Object tempObj : tempMedias) {
					if(!StringUtils.equals(type, WxMaterialTypeEnum.text.name()) && !StringUtils.equals(type, WxMaterialTypeEnum.news.name())) {
						WxMaterialMedia tempMedia = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(tempObj)), WxMaterialMedia.class);
						res.add(WxMaterialMedia.getH5JsonMap(tempMedia,WxMaterialTypeEnum.valueOf(type)));
					}else if (StringUtils.equals(type, WxMaterialTypeEnum.news.name())) {
						WxMaterialNews tempMedia = JSON.toJavaObject(JSON.parseObject(JSON.toJSONString(tempObj)), WxMaterialNews.class);
						res.add(WxMaterialNews.getH5JsonMap(tempMedia));
					}
				}
			}
			logger.debug("参数整合结束："+res.size());
		}

		return new Result<List<Map<String, Object>>>(1, res, null);
	}

	@ApiOperation(value = "WX-更新常见对白频次", produces = "application/json; charset=utf-8")
	@RequestMapping(value = "/updateDialogueTimes", method = RequestMethod.GET)
	@ResponseBody
	public Result<Integer> updateDialogueTimes(
//			@RequestBody Integer id
			@RequestParam(value = "id", required = true) Integer id
			) {
		int i = appApiService.updateDialogueTimes(id);
		return new Result<>(1, i, null);
	}

	@ApiOperation(value = "WX-->获取常用对白", produces = "application/json; charset=utf-8")
	@RequestMapping(value = "/getWxChatDialogue", method = RequestMethod.GET)
	@ResponseBody
	public Result<List<TmChatDialogue>> getWxChatDialogue(
//			@RequestBody String dealerCode
			@RequestParam(value = "dealerCode", required = true) String dealerCode
			) {
		logger.info("getWxChatDialogue==>");
		List<TmChatDialogue> page = appApiService.getWxChatDialogue(dealerCode);
		return new Result<List<TmChatDialogue>>(1, page, null);
	}

	/**
	 * 记录时间显示
	 * 
	 * @author qianjs163@163.com 2017年11月23日 下午3:14:39
	 * @return
	 */
	@RequestMapping(value = "/wx_addDateShow", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "记录时间显示", notes = "记录时间显示")	
	public Result<Integer> addDateShow(
			@RequestBody Long msgId
//			@RequestParam(value = "msgId", required = true) Long msgId
			) {
		logger.info("记录时间显示");
		return new Result<Integer>(1, wxUserService.upDateShow(msgId), null);
	}
	
	/**
	 * 查询用户信息
	 * @param query
	 * @return
	 */
//	@RequestMapping(value = "/wx_getLKUserInfo", method = RequestMethod.POST)
//	@ResponseBody
//	@ApiOperation(value = "获取用户信息", notes = "获取用户信息")	
//	public List<TmCarOwnerVo> getLKUserInfo(TmCarOwner query){// 修改：从林肯后台、
//		if(query.getUserId()!=null) {
//			Integer userId = wxChatUserService.getChatUserIdByLKUserId(query.getUserId());
//			query.setUserId(userId);
//		}
//		List<TmCarOwner> userInfos = tmCarOwnerMapper.select(query);
//		List<TmCarOwnerVo> resList = new ArrayList<TmCarOwnerVo>();
//		for(TmCarOwner temp : userInfos) {
//			TmCarOwnerVo resEntity = new TmCarOwnerVo();
//			resEntity.setUserId(temp.getUserId().toString());
//			resEntity.setName(temp.getNickname());
//			resEntity.setJmessage(temp.getJmessageCode());
//			resEntity.setJpassword("123456");
//			resEntity.setPhone(temp.getPhone());
//			resEntity.setPicUrl(temp.getIconsPhoto());
//			resList.add(resEntity);
//		}
//		return resList;
//	}
	
	/**
	 * 查询客服信息
	 * @param query
	 * @return
	 */
	@RequestMapping(value = "/wx_getChatInfo", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "获取客服信息，客服上线", notes = "获取客服信息id为客服ID，userId为林肯后台userId，wxUserId为企业号登录后的userId")
	public List<TrUserEnterprise> getChatInfo(@RequestBody TrUserEnterprise query){
		logger.debug("客服上线，第一次获取客服信息："+query);
		logger.debug("请验证：企业号上线传的是 phone ；PC上线传的 是 userId");
		// 企业号 传的是 phone PC 传的 是 id
		String phone = query.getPhone();
		String userId = query.getUserId();
		if(StringUtils.isNotEmpty(phone)) {
			query = new TrUserEnterprise();
			query.setPhone(phone);
		}else if(StringUtils.isNotEmpty(userId)) {
			query = new TrUserEnterprise();
			query.setUserId(userId);
		}
		logger.debug("获取客服的查询条件："+query);
		List<TrUserEnterprise> userInfos = trUserEnterpriseMapper.select(query);
		logger.debug("获取客服信息："+userInfos);
		if(userInfos!=null && userInfos.size()==1) {// 若是用户登录后获取用户信息，则判断Jmessage账号是否存在，不存在，则注册
			logger.debug("客服注册jmessage账号开始");
			controllerImpl.registerJmessageCodeForChat(userInfos);
			logger.debug("客服注册jmessage账号结束");
			// 客服上线
			logger.debug("开始记录客服登录日志");
			WxChatLoginLog loginEntity = new WxChatLoginLog();
			loginEntity.setWxUserId(Integer.valueOf(userInfos.get(0).getUserId()));
			loginEntity.setAppType(StringUtils.isEmpty(query.getUserId()) ? WxChatLoginLog.APP_QY : WxChatLoginLog.APP_PC);
			wxChatLoginLogService.insert(loginEntity);
			logger.debug("记录客服登录日志结束");
		}
		return userInfos;
	}
	/**
	 * 会话列表接口-根据用户ID获取当天聊过天的用户
	 * 
	 * */
	@RequestMapping(value = "/wx_getChatUserList", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "会话列表", notes = "会话列表")	
	public List<TmCarOwnerVo> getChatUserList(@RequestParam(value = "userId", required = true) Integer userIdlk){
		// 根据后台用户ID获取对应的客服ID
		Integer userId = wxChatUserService.getChatUserIdByLKUserId(userIdlk);
		Map<String,Object> paramMap = new HashMap<String,Object>();
		paramMap.put("userId", Integer.valueOf(userId));
		List<Map<String,Object>> userInfos = wxUserService.getWxChatList(Integer.valueOf(userId),WxUserOwner.STATUS_USEFUL);
		List<TmCarOwnerVo> resList = new ArrayList<TmCarOwnerVo>();
		List<String> resIds = new ArrayList<String>();
		for(Map<String,Object> temp : userInfos) {
			if(temp.get("owner_code")!=null) {
				resIds.add(String.valueOf(temp.get("owner_code")));
			}
		}
		// 取出最后的消息
		Map<String,H5MessageVo> lastContentMap = new HashMap<String,H5MessageVo>();
		for(Map<String,Object> temp : userInfos) {
			if(temp.get("owner_code")!=null) {
//				Map<String,String> lastContent = new HashMap<String,String>();
				H5MessageVo lastContent = new H5MessageVo();
				lastContent.setContent(String.valueOf(temp.get("last_content")));
				lastContent.setType(WxMaterialTypeEnum.valueOf(String.valueOf(temp.get("last_content_type"))));
				String lastTimeStr = String.valueOf(temp.get("last_time"));
				lastContent.setLastTime(DateUtil.parseDate(lastTimeStr,DateUtil.FORMAT_STANDARD_PATTERN).getTime());
				lastContentMap.put(String.valueOf(temp.get("owner_code")), lastContent);
			}
		}
		if(CollectionUtils.isNotEmpty(resIds)) {
			List<TmPotentialUser> resDtos = ownerService.queryOwnerByIds(resIds);
			for(TmPotentialUser temp : resDtos) {
				TmCarOwnerVo resEntity = new TmCarOwnerVo();
				resEntity.setUserId(temp.getPotentialUserId().toString());
				resEntity.setName(temp.getNickname());
				resEntity.setJmessage(temp.getJmessageCode());
				resEntity.setJpassword(JmessageUserUtil.JMESSAGE_DEFAULT_PASS);
				resEntity.setPhone(temp.getRegisterPhone());
				resEntity.setPicUrl(temp.getHeadImgurl());
				H5MessageVo lastContent = lastContentMap.get(String.valueOf(temp.getPotentialUserId()));
				lastContent.setFromUser(temp);
				resEntity.setLastContent(lastContent);
				resEntity.setLastContentType(resEntity.getLastContent().getType());
				resList.add(resEntity);
			}
		}
		return resList;
	}
	/**
	 * 在客服主动断开链接之后，需要告诉公众号：此用户已经和客服断开链接了，如需服务，再次分配客服
	 * 客服断开聊天链接的接口，有多个地方调用，再此做个标志，标识是直接调用本方法，还是其他地方调用。
	 * 其他地方调用本方法的时候，按照需要，修改是否断开公众号客户聊天链接标志位。
	 */
	private boolean isDisConnect = true;
	/**
	 * 客服主动断开和客户的链接
	 * @throws Exception 
	 * */
	@RequestMapping(value = "/wx_deleteChatOwner", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "客服主动断开和客户的链接", notes = "客服主动断开和客户的链接")
	public Result<String> deleteChatOwner(@RequestParam(value = "userId", required = true) Integer userIdlk,
			@RequestParam(value = "ownerCode", required = true) String ownerCode) throws Exception{
		logger.debug("客服"+userIdlk+"将要移除聊天中的用户："+ownerCode);
		Integer userId = wxChatUserService.getChatUserIdByLKUserId(userIdlk);
		Result<String> res = new Result<String>(1, "SUCCESS", null);
		logger.debug("客服主动断开聊天链接："+userId+" - "+ownerCode);
		logger.debug("断开链接 之前，首先判断等待队列中是否存在等待人");
		// 判断等待队列中是否存在等待的用户，有则直接建立链接，然后把用户发送的消息发送过去
		ChatWaitQueueService queueService = ChatWaitQueueService.newInstance();
		ChatMsgDetailDto chatQueueUserMsg = queueService.getChatQueueUser(userId.toString());
		logger.debug("获取等待队列："+chatQueueUserMsg);
		if(chatQueueUserMsg!=null) {
			logger.debug("等待队列中存在等待人，则先把客服可等待人建立强制链接，并发送消息之后，再断开客服和原用户之间的聊天链接");
			TmPotentialUser queryPuser = new TmPotentialUser();
			queryPuser.setPotentialUserId(new BigDecimal(chatQueueUserMsg.getFormeUser()));
			TmPotentialUser owner = tmPotentialUserMapper.selectOne(queryPuser);
			logger.debug("查询出用户信息："+owner);
			wxUserService.coerceCreateConnect(userId,owner,chatQueueUserMsg.getContent(),chatQueueUserMsg.getMsgType());
			logger.debug("强制建立链接："+userId+" - "+owner.getPotentialUserId());
			logger.debug("强制建立链接之后，发送客服等待中的消息");
			// 发送用户消息
			WxGzMessageDto msgDto = new WxGzMessageDto();
			// 未完成，此处的消息较难处理，按照普通消息发送，除非发送消息的方法支持一次发送多条消息；
			// 若在这里多次调用的话，很长一段代码和数据库操作都在同步状态，容易造成阻塞
			msgDto.setContent(chatQueueUserMsg.getContent());
			msgDto.setCreateTime(DateUtil.format(chatQueueUserMsg.getCreateTime(),DateUtil.FORMAT_STANDARD_PATTERN));
			msgDto.setFromUserName(owner.getDeviceOpenId());
			msgDto.setMsgType(chatQueueUserMsg.getMsgType().name());
			logger.debug("强制建立链接之后，发送消息给客服："+msgDto);
			res = chatController.getWxgzMsg(msgDto);
			logger.debug("强制建立链接之后，发送客服等待中的消息结果："+res);
			// 从队列中移除等待者
			logger.debug("移除等待队列中的等待者:"+owner.getPotentialUserId().toString());
			queueService.removeChatQueueUser(userId.toString(), owner.getPotentialUserId().toString());
			logger.debug("整个过程完成，等待者已从队列中移除，请查看消息等待队列确认");
		}
		logger.debug("等待队列操作完毕之后 ，在做真正的聊天链接断开工作");
		wxUserService.deleteChatOwnerRel(userId,ownerCode);
		// 断开用户聊天链接
		if(isDisConnect) {
			logger.debug("开始断开公众号用户聊天链接");
			TmPotentialUser queryPuser = new TmPotentialUser();
			queryPuser.setPotentialUserId(new BigDecimal(ownerCode));
			TmPotentialUser owner = tmPotentialUserMapper.selectOne(queryPuser);
			if(owner==null) {
				return new Result(ChatErrorCode.NO_APP_USER, null, "no app user!");
			}
			logger.debug("查询到需要公众号断开用户聊天链接的用户信息："+owner);
			weChatPushServiceInterface.disconnect(owner.getDeviceOpenId());
			logger.debug("断开公众号用户聊天链接完成");
		}
		// 不管是否操作，重置标志位
		isDisConnect = true;
		return res;
	}
	
	/**
	 * 获取所有可转接客服
	 * @throws Exception 
	 * */
	@RequestMapping(value = "/wx_getAllInlineChats", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "获取所有可转接客服", notes = "BUKA001")
	public Result<List<ChangeChatVo>> getAllInlineChats(
			@RequestParam(value = "dealerCode", required = true) String dealerCode) throws Exception{
		logger.debug("获取销售店"+dealerCode+"所有可转接客服");
		Result<List<ChangeChatVo>> result = new Result<List<ChangeChatVo>>(1, null, null);
		TrUserEnterprise allInlineChatQuery = new TrUserEnterprise();
		allInlineChatQuery.setJmessageStatus(1);
		allInlineChatQuery.setDealerCode(dealerCode);
		List<TrUserEnterprise> allInlineChatList = trUserEnterpriseMapper.select(allInlineChatQuery);
		logger.debug("获取所有在线状态的客服"+allInlineChatList);
		if(allInlineChatList==null) {
			logger.debug("目前没有在线状态的客服");
			result.setReturnFlag(ChatErrorCode.CHAT_NO_ONLINE);
			result.setErrorMsg("目前没有在线状态的客服");
			return result;
		}
		// 即使客服很忙，也要允许转接，转接之后，排队即可
//		List<String> leisurestChatIds = wxUserService.getLeisurestChat(allInlineChatList);
//		logger.debug("获取空闲客服列表结果："+leisurestChatIds);
//		if(CollectionUtils.isEmpty(leisurestChatIds)) {
//			logger.debug("目前没有空闲的在线客服");
//			result.setReturnFlag(ChatErrorCode.CHAT_NO_LEISUREST);
//			result.setErrorMsg("目前没有空闲的在线客服");
//			return result;
//		}
//		List<TrUserEnterpriseVo> chats = wxUserService.queryChatsByIds(leisurestChatIds);
		List<TrUserEnterpriseVo> chats = new ArrayList<TrUserEnterpriseVo>();
		for(TrUserEnterprise tempEntity : allInlineChatList) {
			TrUserEnterpriseVo newTempEntity = new TrUserEnterpriseVo();
			BeanUtils.copyProperties(newTempEntity, tempEntity);
			chats.add(newTempEntity);
		}
		List<ChangeChatVo> res = new ArrayList<ChangeChatVo>();
		ChangeChatVo changechatEntity = new ChangeChatVo();
		changechatEntity.setDepartment("OEM客服");
		changechatEntity.setList(chats);
		res.add(changechatEntity);
		result.setData(res);
		return result;
	}
	@RequestMapping(value = "/wx_changeChatForUser", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "客服转接", notes = "srcChatId 转接前客服ID,tarChatId目标客服ID,ownerCode用户code，message消息内容，messageType消息类型")
	public Result<String> getAllInlineChats(@RequestBody WxChatUserChangDto change
			) throws Exception{
		// 未完成，这里存在问题：由于此方法内包含断开原有链接，建立新链接的逻辑，而且这些逻辑并不在一个事务中，所以此处可能造成一半成功，一半失败的情况，上线前尽快修复
		String srcChatId = change.getSrcChatId();
		String tarChatId = change.getTarChatId() ;
		String ownerCode = change.getOwnerCode() ;
		String message = change.getMessage() ;
		String messageType = change.getMessageType() ;
		logger.debug("将用户"+ownerCode+"从客服"+srcChatId+"转接到客服"+tarChatId);
		logger.debug("转接参数：srcChatId："+srcChatId+"；tarChatId："+tarChatId+"；ownerCode："+ownerCode+"；message："+message+"；messageType："+messageType+"；");
// 为了保证安全，要判断目标用户、目标客服是否存在
		// 首先转化openID为userId
		TmPotentialUser queryPuser = new TmPotentialUser();
		queryPuser.setPotentialUserId(new BigDecimal(ownerCode));
		TmPotentialUser owner = tmPotentialUserMapper.selectOne(queryPuser);
		if(owner==null) {
			return new Result(ChatErrorCode.NO_APP_USER, null, "no app user!");
		}
		logger.debug("查询到用户信息："+owner);
		// 根据wxUsserCode获取客服信息
		TrUserEnterprise wxChatUser = new TrUserEnterprise();
		wxChatUser.setUserId(tarChatId);
		wxChatUser = wxChatUserService.getOne(wxChatUser);
		if (wxChatUser == null) {
			return new Result(ChatErrorCode.NO_WX_USER, null, "no wx user!");
		}
		logger.debug("查询到目标客服："+wxChatUser);
		// 要首先判断此客服是否还有对此用户操作的权限，如果当前客服和客户之间的链接已经断开，则无法发送消息 ，也无法转接和其他操作。
//		WxUserOwner userForChat = wxUserService.getWxUserOwner(srcChatId, ownerCode);
		// 为了保证业务的正常进行，客服不允许向未练级的用户发送消息
//		if(userForChat==null || userForChat.getStatus()==0) {
//			return new Result<String>(0,null,"和此用户的聊天链接已断开");
//		}
// 首先判断目标客服是否在线
		// 判断是否在线
		Boolean onlineFlag = false;
		Result<Map> onlineResult = userOperator.getUserState(wxChatUser.getJmessageCode());
		Result<Map> onlineResultQYH = userOperator.getUserState(wxChatUser.getWxJmessageCode());
		// 判断PC端是否在线
		if (onlineResult.getReturnFlag() == 1 && onlineResult.getData() != null) {
			onlineFlag = (Boolean) onlineResult.getData().get("online");
			logger.debug("查询客服"+wxChatUser.getUserId()+"PC是否在线："+onlineFlag);
		}
		// 判断企业号是否在线，只要有一端在线即可
		if (!onlineFlag && onlineResultQYH.getReturnFlag() == 1 && onlineResultQYH.getData() != null) {
			onlineFlag = (Boolean) onlineResultQYH.getData().get("online");
			logger.debug("查询客服"+wxChatUser.getUserId()+"企业号是否在线："+onlineFlag);
		}
		logger.debug("查询客服"+wxChatUser.getUserId()+"是否在线："+onlineFlag);
		// 顺便更新一下在线状态
		wxChatUser.setJmessageStatus(onlineFlag ? WxUserOwner.STATUS_USEFUL : WxUserOwner.STATUS_NOUSE);
		wxChatUserService.updateChatInfo(wxChatUser);
		if(!onlineFlag) {
			// 如果不在线，则直接返回
			return new Result(ChatErrorCode.CHAT_OFFLINE, null,"转接目标客服不在线");
		}
// 其次判断目标客服是否忙碌
		List<TrUserEnterprise> queryBusyChat = new ArrayList<TrUserEnterprise>();
		queryBusyChat.add(wxChatUser);
		List<String> leisurestChat = wxUserService.getLeisurestChat(queryBusyChat);
// 若目标客服忙碌，但等待队列不满，则加入到客服的等待队列中（这部分可以先不做）
		if(CollectionUtils.isEmpty(leisurestChat)) {
			if(!chatQueueService.isFullQueue(tarChatId)) {
				ChatMsgDetailDto msgDetail = new ChatMsgDetailDto();
				msgDetail.setContent(message);
				msgDetail.setFormeUser(ownerCode);
				msgDetail.setMsgType(WxMaterialTypeEnum.valueOf(messageType));
				msgDetail.setCreateTime(new Date());
				chatQueueService.addQueue(tarChatId, msgDetail);
			}
		}else {
// 若目标客服不忙，则建立目标客服和用户之间的链接
			wxUserService.coerceCreateConnect(wxChatUser.getId().intValue(),owner,message,WxMaterialTypeEnum.valueOf(messageType));
		}
// 删除目标用户和原客服之间的聊天链接
		deleteChatOwner(Integer.valueOf(srcChatId), ownerCode);
// 发送用户的转接消息给目标客服
		// 发送用户消息
		WxGzMessageDto msgDto = new WxGzMessageDto();
		// 未完成，此处的消息较难处理，按照普通消息发送，除非发送消息的方法支持一次发送多条消息；
		// 若在这里多次调用的话，很长一段代码和数据库操作都在同步状态，容易造成阻塞
		msgDto.setContent(message);
		msgDto.setCreateTime(DateUtil.format(new Date(),DateUtil.FORMAT_STANDARD_PATTERN));
		msgDto.setFromUserName(owner.getDeviceOpenId());
		msgDto.setMsgType(messageType);
		logger.debug("强制建立链接之后，发送消息给客服："+msgDto);
		Result<String> res = chatController.getWxgzMsg(msgDto);
		logger.debug("强制建立链接之后，发送客服等待中的消息结果："+res);
		return res;
	}
	@RequestMapping(value = "/wx_getToken", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "获取微信token方便测试", notes = "")
	public Result<String> getToken(){
		Result<String> res = new Result<String>();
		res.setData(weChatPushServiceInterface.getWxPublishToken());
		return res;
	}
	@RequestMapping(value = "/wx_chatLoginOut", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "客服主动下线", notes = "客服ID")
	public Result<String> chatLoginOut(@RequestParam("chatId") Integer chatId) throws NumberFormatException, Exception{
		logger.debug("客服主动下线："+chatId);
		Result<String> res = new Result<String>();
		// 首先修改客服在线状态
		trUserEnterpriseMapper.loginOut(chatId);
		// 然后执行客服下线之后的操作：
		// 最后处理客服的等待队列，重新设置可等待客服
		TrUserEnterprise allInlineChatQuery = new TrUserEnterprise();
		allInlineChatQuery.setJmessageStatus(1);
		List<TrUserEnterprise> allInlineChatList = trUserEnterpriseMapper.select(allInlineChatQuery);
		List<String> chats = new ArrayList<String>();
		for(TrUserEnterprise chat : allInlineChatList) {
			chats.add(chat.getUserId());
		}
		chatQueueService.setUsefulChats(chats);
		// 然后断开所有和客服聊天的链接（不管是否有效）
		List<Map<String,Object>> userInfos = wxUserService.getWxChatList(chatId,WxUserOwner.STATUS_USEFUL);
		for(Map<String,Object> chatUser : userInfos) {
			this.deleteChatOwner(Integer.valueOf(String.valueOf(chatUser.get("wx_user_id"))), String.valueOf(chatUser.get("owner_code")));
		}
		res.setReturnFlag(ChatErrorCode.SUCCESS);
		wxChatLoginLogService.loginOut(chatId);
		logger.debug("客服主动下线："+chatId+"  完成");
		return res;
	}
	
	/**
	 * 导出聊天对话信息 - 聊天记录
	 * 
	 * @param ownerCode
	 * @param userId
	 * @param model
	 * @return
	 * @throws IntrospectionException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 */
	@RequestMapping(value = "/wx_chat_talk_export", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "导出聊天对话信息", 
	notes = "wxUserId请传递后台用户的ID")	
	public Result<String> wxChatTalkExport( @RequestBody WxChatLogExportDto searchDto) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
		Integer userIdLk = searchDto.getWxUserId();
		String userId = wxChatUserService.getChatUserIdByLKUserId(userIdLk)+"";
		logger.info("获取聊天详情:wxChatTalk");
		List<WxChatLogExportVo> list = wxUserService.exportWxChatTalk(searchDto);
		List<Pair> headers = new ArrayList<Pair>();
//		Pair userIdPair = new Pair("sessionId","车型名称");
//		Pair userIdPair = new Pair("title","车型名称");
//		Pair userIdPair = new Pair("url","车型名称");
		headers.add(new Pair("wxUserId","客服ID"));
		headers.add(new Pair("wxUserName","客服昵称"));
		headers.add(new Pair("dealerCode","经销商代码"));
		headers.add(new Pair("dealerName","经销商名称"));
		headers.add(new Pair("ownerCode","用户ID"));
		headers.add(new Pair("ownerName","用户昵称"));
		headers.add(new Pair("ownerModel","车型代码"));
		headers.add(new Pair("ownerModelName","车型名称"));
		headers.add(new Pair("content","聊天文本"));
		headers.add(new Pair("contentType","文本类型"));
		headers.add(new Pair("crtTime","消息时间"));
		headers.add(new Pair("direction","发送方"));
		List<Map<String,Object>> data = BeanMapUtil.convertBeansToMap(list);
		String fileUrl = SimpleExcelExport.getFileStoreDownloadUrl(headers, data,DateUtil.format(new Date(), "HHmmssSSS") + RandomNum.createRandomString(6) + ".xls");
		return new Result(1, fileUrl, null);
	}

	public boolean isDisConnect() {
		return isDisConnect;
	}

	public void setDisConnect(boolean isDisConnect) {
		this.isDisConnect = isDisConnect;
	}
}
